package tl;

import java.lang.ref.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author fei
 * @date 2023/1/27 10:33
 * @description java四大引用
 */
public class ReferenceDemo {

    public static void main(String[] args) {
        ReferenceQueue<MyObject> referenceQueue = new ReferenceQueue();
        PhantomReference<MyObject> phantomReference = new PhantomReference<>(new MyObject(),referenceQueue);

        List<byte[]> list = new ArrayList<>();

        new Thread(() -> {
            while (true)
            {
                list.add(new byte[1 * 1024 * 1024]);
                try { TimeUnit.MILLISECONDS.sleep(600); } catch (InterruptedException e) { e.printStackTrace(); }
                System.out.println(phantomReference.get());
            }
        },"t1").start();

        new Thread(() -> {
            while (true)
            {
                Reference<? extends MyObject> reference = referenceQueue.poll();
                if (reference != null) {
                    System.out.println("***********有虚对象加入队列了");
                }
            }
        },"t2").start();

        //暂停几秒钟线程
        try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); }
    }

    /**
     * 弱引用
     */
    private static void weakReference() {
        WeakReference<MyObject> weakReference = new WeakReference<>(new MyObject());
        System.out.println("-------gc before内存够用：" + weakReference.get());

        System.gc();
        try{ TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) { e.printStackTrace(); }

        System.out.println("-------gc after内存够用：" + weakReference.get());
    }

    /**
     * 软引用
     */
    private static void softReference() {
        // 当我们内存不够用的时候，soft会被回收的情况，设置我们的内存大小：-Xms10m -Xmx10m
        SoftReference<MyObject> softReference = new SoftReference<>(new MyObject());

        System.gc();
        try{ TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) { e.printStackTrace(); }
        System.out.println("-------gc after内存够用：" + softReference.get());

        // 这里如果想要看到结果，就要改一下java虚拟机参数
        // -Xms10m -Xmx10m
        try{
            // 20MB 对象
            byte[] bytes = new byte[20 * 1024 * 1024];
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            System.out.println("------ gc after内存不够：" + softReference.get());
        }
    }

    /**
     * 强引用
     */
    private static void strongReference() {
        MyObject myObject = new MyObject();
        System.out.println("gc before: " + myObject);

        myObject = null;
        // 人工开启 GC，一般不用
        System.gc();

        try{ TimeUnit.MILLISECONDS.sleep(500);} catch (InterruptedException e) { e.printStackTrace(); }
        System.out.println("gc after: " + myObject);
    }

}

class MyObject {
    /**
     * 一般开发中不用调用这个方法，本次只是为了演示
     * finalize 的通常目的是在对象被不可撤销地丢弃之前执行清理操作
     * @throws Throwable
     */
    @Override
    protected void finalize() throws Throwable {
        System.out.println(Thread.currentThread().getName() + "\t" + "---finalize method invoked....");
    }
}